package org.jxy.study.rpc.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.net.SocketAddress;
import javax.annotation.Resource;
import org.jxy.study.rpc.message.Request;
import org.jxy.study.rpc.message.Response;
import org.jxy.study.rpc.netty.hander.ByteMsgToDataMsgDecoder;
import org.jxy.study.rpc.netty.hander.DataMsgToByteMsgEncoder;
import org.jxy.study.rpc.netty.hander.DataMsgToRequestOrResponseConvert;
import org.jxy.study.rpc.netty.hander.NettyClientResponseHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author : porteryao
 * @description : 描述
 * @date : 2021/3/11 19:04
 */
@Component
public class NettyClient {

    Logger logger = LoggerFactory.getLogger(NettyClient.class);

    private NioEventLoopGroup loopGroup = new NioEventLoopGroup();
    private Bootstrap bootstrap = new Bootstrap();
    @Resource
    private NettyClientResponseHandler clientResponseHandler;
    @Resource
    private ConnectManage connectManage;

    public NettyClient() {
        bootstrap.group(loopGroup)
            .channel(NioSocketChannel.class)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    pipeline.addLast(new ByteMsgToDataMsgDecoder());
                    pipeline.addLast(new DataMsgToByteMsgEncoder());
                    pipeline.addLast(new DataMsgToRequestOrResponseConvert(Response.class));
                    pipeline.addLast(clientResponseHandler);
                }
            });
    }

    public Channel connect(SocketAddress address) throws InterruptedException {
        ChannelFuture future = bootstrap.connect(address);
        Channel channel = future.sync().channel();
        return channel;
    }

    public Response sendMsg(Request request) throws InterruptedException {
        Channel channel = connectManage.chooseChannel();
        if (channel == null || (!channel.isActive())) {
            logger.error("通道不可用!");
            Response res = new Response();
            res.setCode(500);
            res.setErrorMsg("通道不可用!");
            return res;
        }
        //正常发送待解决
        return clientResponseHandler.sendMsg(channel, request).take();
    }
}
